package com.qys.livesMall.financial.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qys.livesMall.app.user.model.entity.AppUserLevel;
import com.qys.livesMall.app.user.model.entity.H2AppUser;
import com.qys.livesMall.app.user.service.AppUserLevelService;
import com.qys.livesMall.app.user.service.IH2AppUserService;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.utils.DateUtils;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.model.entity.user.FinanceUserAccount;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.finance.service.FinanceUserAccountService;
import com.qys.livesMall.financial.model.dto.app.AppFinancialOnlinePageDTO;
import com.qys.livesMall.financial.model.dto.app.TakeFinancialOnlineDTO;
import com.qys.livesMall.financial.model.dto.sys.FinancialOnlinePageDTO;
import com.qys.livesMall.financial.model.dto.sys.FinancialOnlineSaveDTO;
import com.qys.livesMall.financial.model.entity.FinancialOnline;
import com.qys.livesMall.financial.mapper.FinancialOnlineMapper;
import com.qys.livesMall.financial.model.entity.FinancialOnlineDetail;
import com.qys.livesMall.financial.model.vo.FinancialOnlineVO;
import com.qys.livesMall.financial.model.vo.app.AppFinancialOnlinePageVO;
import com.qys.livesMall.financial.model.vo.sys.FinancialOnlinePageVO;
import com.qys.livesMall.financial.service.FinancialOnlineDetailService;
import com.qys.livesMall.financial.service.FinancialOnlineService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.livesMall.financial.service.FinancialOnlineUserService;
import com.qys.livesMall.framework.utils.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 线上理财表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-06-13
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class FinancialOnlineServiceImpl extends ServiceImpl<FinancialOnlineMapper, FinancialOnline> implements FinancialOnlineService {

    private final AppUserLevelService userLevelService;
    private final FinancialOnlineDetailService onlineDetailService;
    private final IH2AppUserService userService;
    private final FinanceBusinessService financeBusinessService;

    private final FinanceUserAccountService financeUserAccountService;
    private final FinancialOnlineUserService onlineUserService;

    @Override
    public Page<FinancialOnlinePageVO> pageBySys(FinancialOnlinePageDTO pageDTO) {
        Page<FinancialOnlinePageVO> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        page=baseMapper.listBySysPage(page, pageDTO);
        return page;
    }

    @Override
    public Page<AppFinancialOnlinePageVO> pageByApp(AppFinancialOnlinePageDTO pageDTO) {
        Page<AppFinancialOnlinePageVO> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        page=baseMapper.listByAppPage(page, pageDTO);
        return page;
    }

    @Override
    public void saveOrUpdate(FinancialOnlineSaveDTO saveDTO) {
        log.info("管理员操作任务信息,操作人：{}，操作信息：{}", SecurityUtils.getUsername(), saveDTO);
        //等级
        AppUserLevel userLevel = userLevelService.getById(saveDTO.getLimitUserLevel());
        if (null == userLevel) {
            throw new QysException(MessageUtils.message("user.level.null"));
        }
        FinancialOnline online = new FinancialOnline();
        BeanUtils.copyProperties(saveDTO, online);
//        online.setStartTime(DateUtils.toLocalDateTime(new Date(saveDTO.getStartTime())));
//        online.setFinishTime(DateUtils.toLocalDateTime(new Date(saveDTO.getFinishTime())));
        online.setInterestRate(saveDTO.getInterestRate().divide(new BigDecimal("100"), 4, RoundingMode.DOWN));
        if (null == saveDTO.getId()) {
            //save
            if (null!= saveDTO.getBuyUser() && saveDTO.getBuyUser() > saveDTO.getDummyUser()) {
                throw new QysException(MessageUtils.message("financial.online.buy"));
            }
            online.setDeleted((byte) 0);
            online.setStatus((byte) 0);
            online.setCreateTime(LocalDateTime.now());
            online.setCreateBy(SecurityUtils.getUsername());

        } else {
            FinancialOnline financialOnline=getById(saveDTO.getId());
            //update
            if (saveDTO.getDummyUser() < saveDTO.getBuyUser() + financialOnline.getRealityCount()) {
                throw new QysException(MessageUtils.message("financial.online.buy"));
            }
            online.setUpdateTime(LocalDateTime.now());
            online.setUpdateBy(SecurityUtils.getUsername());
        }
        saveOrUpdate(online);
    }

    @Override
    public void deleteById(Long id) {
        log.info("管理员执行线上理财删除操作,操作人：{}，操作信息：{}", SecurityUtils.getUsername(), id);
        FinancialOnline online = baseMapper.selectById(id);
        if (online.getStatus() == 1) {
            throw new QysException(MessageUtils.message("financial.online.status"));
        }
        long count = onlineDetailService.count(Wrappers.<FinancialOnlineDetail>lambdaQuery()
                .eq(FinancialOnlineDetail::getOnlineFinancialId, id));
        if (count > 0) {
            throw new QysException(MessageUtils.message("financial.online.buyed"));
        }
        baseMapper.deleteById(id);
    }

    @Override
    public void shelves(Long id) {
        log.info("管理员执行线上理财上下架操作,操作人：{}，操作信息：{}", SecurityUtils.getUsername(), id);
        FinancialOnline online = baseMapper.selectById(id);
        if (null == online) {
            throw new QysException(MessageUtils.message("financial.online.null"));
        }
        online.setStatus((byte) (online.getStatus() == 0 ? 1 : 0));
        baseMapper.updateById(online);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void takePartIn(TakeFinancialOnlineDTO takeDTO) {
        Long userId = SecurityUtils.getUserId();
        boolean isFlag = userService.checkPassWord(userId, takeDTO.getPayPassword(), 1);
        if (!isFlag){
            throw new QysException(MessageUtils.message("password.error"));
        }
        synchronized (takeDTO.getOnlineFinancialId()) {
            FinancialOnline onlineFinancial = getById(takeDTO.getOnlineFinancialId());
            //校验状态
            if(!Objects.equals(onlineFinancial.getStatus().intValue(),Constants.YesNoInt.YES)){
                throw new QysException(MessageUtils.message("financial.online.status"));
            }
            checkTakePartIn(userId, Long.valueOf(onlineFinancial.getLimitUserLevel()));
        //购买人数
//        long count = onlineDetailService.count(Wrappers.<FinancialOnlineDetail>lambdaQuery()
//                .eq(FinancialOnlineDetail::getOnlineFinancialId, takeDTO.getOnlineFinancialId()));

            if (onlineFinancial.getRealityCount() + onlineFinancial.getBuyUser() >= onlineFinancial.getDummyUser()) {
                throw new QysException(MessageUtils.message("购买名额已满"));
            }
            //重复购买问题
            long count1 = onlineDetailService.count(Wrappers.<FinancialOnlineDetail>lambdaQuery()
                    .eq(FinancialOnlineDetail::getOnlineFinancialId, takeDTO.getOnlineFinancialId())
                    .eq(FinancialOnlineDetail::getUserId, userId)
            );
            if (count1 > 0) {
                throw new QysException(MessageUtils.message("已购买该理财产品"));
            }

//        LocalDateTime date = LocalDateTime.now();
//        //开始时间之前
//        if (date.isBefore(onlineFinancial.getStartTime())) {
//            throw new QysException(MessageUtils.message("该理财产品尚未开启购买"));
//        }

            FinancialOnlineDetail record = onlineDetailService.init(onlineFinancial, userId, onlineFinancial.getMaxAmount(), takeDTO.getContract());
            //添加用户预估收益
            onlineUserService.generateUserIncome(record);

            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(userId);
            payDTO.setBusinessNo(record.getOrderNo());
            payDTO.setAmountIncurred(onlineFinancial.getMaxAmount());
            payDTO.setBusinessType(AccountBusinessTypeEnum.PRODUCT_INVESTMENT);
            financeBusinessService.pay(payDTO);
            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
            onlineFinancial.setRealityCount(onlineFinancial.getRealityCount()+1);
            updateById(onlineFinancial);
        }
    }

    @Override
    public boolean checkTakePartIn(Long userId, Long limitUserLevel) {
        H2AppUser user = userService.getById(userId);//查询用户
        if (!Objects.equals(user.getUserLevelId(), limitUserLevel)) {
            throw new QysException(MessageUtils.message("用户等级不匹配"));
        }
        AppUserLevel userLevel = userLevelService.getById(user.getUserLevelId());
        if (userLevel.getOnlineFinancialFlag() == 2) {
            throw new QysException(MessageUtils.message("当前等级不允许购买"));
        }
        FinanceUserAccount balance = financeUserAccountService.get(userId);
        if (balance.getTotalBalance().compareTo(userLevel.getKeepAmount()) < 0) {
            throw new QysException(MessageUtils.message("维持等级的金额不足"));
        }
        return true;
    }

    @Override
    public FinancialOnlineVO getinfo(Long id) {
        FinancialOnlineVO financialOnlineVO=new FinancialOnlineVO();
        FinancialOnline financialOnline = getById(id);
        if (null !=financialOnline){
            BeanUtil.copyProperties(financialOnline,financialOnlineVO);
        }
        return financialOnlineVO;
    }


}
